/* 2º Trabalho de Linguagens de Programação
  Criado por: Rafael Couvinha nº 5631
  Contacto: Rafael_couvinha@live.com.pt */

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <Python.h>


int contagem;

/* Este método permitir-nos-à comparar dois valores de forma a saber se são iguais,
   ou qual deles é o maior.
   Recebe um valor a do tipo int*, que será o valor a ser conparado.
   Recebe um valor b do tipo int*, que será o valor a ser comparado
   Devolve uma variavel do tipo inteiro, variando o seu valor conforme o resultado
   da comparação dos dois valores passados por parametro. */
int comp1(const int * a,const int * b)
{
	if (*a==*b){
		return 0;
	}
	else{
		if (*a < *b){
			return -1;
		}
		else{
			return 1;
		}
	}
}

/* Este método permitir-nos-à ordenar a lista recebida por parametro
   através da função da biblioteca standard C qsort(),
   Recebe um valor lista do tipo PyObject, que será a lista a ser ordenada.
   Devolve um valor do tipo PyObject*. */
PyObject* sort_int1(lista){

	int sorting[15]; 
	int i;

	
	for(i = 0; i < PyList_Size(lista); i++ ){
		sorting[i] = PyInt_AsLong(PyList_GetItem(lista, i));
	}

	qsort(sorting,PyList_Size(lista),sizeof(int),comp1) ;

	for (i=0; i < PyList_Size(lista) ; i++){
		PyList_SetItem(lista, i, PyInt_FromLong(sorting[i])) ;
	}	

	
	return lista;
}

/* Este método permitir-nos-à escrever o resultado da query
   efectuada na função list_estab_per_year no ficheiro Lista_sairam.txt,
   Recebe um valor lista do tipo PyObject, que será o valor a ser colocado no ficheiro .txt.
   Recebe um valor estab do tipo char, que será o valor a ser colacado no ficheiro .txt.*/
int writefile1(PyObject* lista, char estab[40]){

	FILE *f1;
	int i;

	f1 = fopen("Lista_sairam.txt", "w");
	fprintf(f1, "Estabelecimento: %s\n " , estab);
	
	for(i = 0; i < PyList_Size(lista); i++){
		fprintf(f1, "Sairam %d docentes.\n " , PyInt_AsLong(PyList_GetItem(lista, i)));
	}
	
	fclose(f1);

	return ;

}

/* Este método permitir-nos-à tratar os dados resultantes da query
   efectuada na função count_year, este método irá passar o valor da query 
   no argv[0] para inteiro e guarda-o na variavel contagem.
   Recebe uma variavel NotUsed do tipo void*, que não será utilizado.
   Recebe uma variavel argc do tipo inteiro, que é o tamanho do array argv
   Recbe uma variavel argv do tipo char**, que é onde será guardado os dados 
   resultantes da query realziada
   Recebe uma variavel azColName do tipo char**, que é o nome das colunas existentes
   na tabela*/
static int callback2(void* NotUsed, int argc, char **argv, char **azColName){

	contagem = atoi( argv[0] ? argv[0] : "NULL");
	
	return 0;
}

/* Este método permitir-nos-à estabelecer a ligação à base de dados rebides
   para que possamos efectuar a query da contagem dos docentes por ano 
   esta ligação e a query é nos possivel utilizando a variavel *db do tipo sqlite3
   Recebe uma variavel ano do tipo int, que é utlizada para realizar a query pretendida.
   Devolve um valor do tipo int*/
int count_year1(int ano, char estab[40]){
	char* name_db= "rebides.db";
	sqlite3 *db;  
	char *zErrMsg = 0;
	int rc;
	char* query;
	char* sAno;
	char* cond;
	
	query = (char *) malloc(sizeof (char[200]));
	cond = (char *) malloc(sizeof (char[50]));
	sAno = (char *) malloc(sizeof (char));

	strcpy(query, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia where ano = ");
	strcpy(cond, " AND estabelecimento = ");
	sprintf(sAno, "%d", ano);
	strcat(query, sAno);
	strcat(cond, estab);
	strcat(query, cond);

	rc = sqlite3_open(name_db, &db);

	rc = sqlite3_exec(db, query, callback2, 0, &zErrMsg);
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);

	free(query);
	free(sAno);
	free(cond);
	return contagem;
}

/* Este método permitir-nos-à realizar a diferença entre o numero de docentes em diferentes
   anos, para que consigamos verificar o numero de docentes que sairam para um determinado
   estabelecimento de ano para ano que será guardado numa lista.
   Para obter o numero de docentes recorre-se à função count_year que devolve a contagem
   dos docentes.
   Por fim será realizada a ordenação da lista resultante através do metodo sort_int().
   Recebe uma variavel estab do tipo char, que é utlizada para realizar a query pretendida.
   Devolve um PyObject* para que este seja reconhecido pelo compilador de Python*/
PyObject* list_leaving_docentes(char estab[40]){
	PyObject* lista = PyList_New(0);
	int i;
	int year1;
	int year2;
	int diference;		
	
	for(i = 10; i > 0; i--){
		year1 = count_year1(i-1, estab);
		year2 = count_year1(i, estab);
		diference = year1 - year2;
		if(diference > 0){
			PyList_Append(lista, PyInt_FromLong(diference));
		}
		else{
			PyList_Append(lista, PyInt_FromLong(0));
		}	
	}

	lista = sort_int1(lista);

	writefile1(lista, estab);

	return  lista;
}